package com.javass.utils;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Locale;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.Version;

/**
 * @ClassName: FreeMarkerUtils
 * @Description: FreeMarker工具类
 * @author Lanxiaowei
 * @date 2014-3-29 下午8:14:58
 */
public class FreeMarkerUtils {
	private static final Version INCOMPATIBLE_IMPROVEMENTS = new Version(2, 3, 23);
	private static ThreadLocal<Configuration> threadLocal = new ThreadLocal<Configuration>();

	public static void remove() {
		threadLocal.remove();
	}

	/**
	 * @Title: initConfig
	 * @Description: 初始化FreeMarker配置对象
	 * @param templatePath
	 *            模版存放路径
	 * @param encoding
	 *            设置模版输出编码
	 * @return
	 */
	public static Configuration initConfig(String templatePath, String encoding) {
		Configuration config = threadLocal.get();
		if (null != config) {
			return config;
		}
		if (null == templatePath || templatePath.trim().length() == 0) {
			throw new RuntimeException("The template path must be provided.");
		}
		if (!templatePath.startsWith("/")) {
			templatePath = "/" + templatePath;
		}
		config = new Configuration(INCOMPATIBLE_IMPROVEMENTS);
		config.setOutputEncoding(encoding);
		config.setEncoding(Locale.CHINA, encoding);
		config.setClassForTemplateLoading(FreeMarkerUtils.class, templatePath);
		threadLocal.set(config);
		return config;
	}

	/**
	 * 初始化FreeMarker配置对象
	 * 
	 * @param context
	 *            配置的上下文：可以是java web <see>javax.servlet.ServletContext</see>,也可以是<see>java.lang.Class</see>对象
	 * @param locale
	 *            环境
	 * @param encoding
	 *            编码
	 * @param templatePath
	 *            路径
	 * @return
	 */
	public static Configuration initConfig(Object context, Locale locale, String encoding, String templatePath) {
		Configuration config = threadLocal.get();
		if (null != config) {
			return config;
		}
		if (null == templatePath || templatePath.trim().length() == 0) {
			throw new RuntimeException("The template path must be provided.");
		}
		if (!templatePath.startsWith("/")) {
			templatePath = "/" + templatePath;
		}
		config = new Configuration(INCOMPATIBLE_IMPROVEMENTS);
		config.setOutputEncoding(encoding);
		config.setEncoding(locale, encoding);
		config.setClassForTemplateLoading(FreeMarkerUtils.class, templatePath);
		threadLocal.set(config);
		return config;
	}

	/**
	 * @Title: initConfig
	 * @Description: 初始化FreeMarker配置对象
	 * @param templatePath
	 *            模版存放路径
	 * @return
	 */
	public static Configuration initConfig(String templatePath) {
		return initConfig(templatePath, "UTF-8");
	}

	/**
	 * @Title: template
	 * @Description: 根据模版 + 数据输出字符串
	 * @param templatePath
	 *            模版存放路径
	 * @param templateName
	 *            模版文件名称
	 * @param dataMap
	 *            要填充到模版的数据
	 * @return
	 */
	public static String template(String templatePath, String templateName, Map<String, Object> dataMap) {
		Configuration config = initConfig(templatePath);
		Template template = null;
		Writer writer = new StringWriter();
		try {
			template = config.getTemplate(templateName);
			template.process(dataMap, writer);
		} catch (TemplateException | IOException e) {
			e.printStackTrace();
		} finally {
			try {
				writer.close();
			} catch (IOException e) {
			}
		}
		return writer.toString();
	}

	/**
	 * @Title: template
	 * @Description: 根据模版 + 数据生成新的内容输出到输出流中
	 * @param templatePath
	 *            模版存放路径
	 * @param templateName
	 *            模版文件名称
	 * @param dataMap
	 *            要填充到模版的数据
	 * @param os
	 *            输出流对象
	 * @param encoding
	 *            输出编码
	 */
	public static void template(String templatePath, String templateName, Map<String, Object> dataMap, OutputStream os,
			String encoding) {
		Configuration config = initConfig(templatePath);
		Template template = null;
		Writer writer = null;
		try {
			template = config.getTemplate(templateName);
			writer = new OutputStreamWriter(os, encoding);
			template.process(dataMap, writer);
			writer.close();
		} catch (TemplateException | IOException e) {
			e.printStackTrace();
		} finally {
			try {
				writer.close();
			} catch (IOException e) {
			}
		}
	}

	/**
	 * @Title: template
	 * @Description: 根据模版 + 数据生成新的内容输出到输出流中
	 * @param templatePath
	 *            模版存放路径
	 * @param templateName
	 *            模版文件名称
	 * @param dataMap
	 *            要填充到模版的数据
	 * @param os
	 *            输出流对象
	 */
	public static void template(String templatePath, String templateName, Map<String, Object> dataMap, OutputStream os) {
		template(templatePath, templateName, dataMap, os, "UTF-8");
	}
}
